#include <iostream>
#include <string.h>
#include "interpretador.h"

using namespace std;

Comandos::Comandos(Comando *atual, Comandos *prox){
	this->atual = atual;
	this->prox = prox;
}

void Comandos::interpreta(Context& c){
	atual->interpreta(c);
	//se houver prox, interpreta o da frente.
	// Como prox e do tipo lista_comands, isto garante 
	// a recursao
	if ( prox != NULL) { prox->interpreta(c);  } 
}

WriteStr::WriteStr(char *palavra){
	this->palavra = palavra;
}

void WriteStr::interpreta(Context& c){
	char * pch;
  pch=strchr(palavra,'"');
	//remove " da string
	while ((pch = strchr(palavra,'"')) != NULL){
		strcpy(pch, pch+1);
	}
	cout << palavra;
}

void Writeln::interpreta(Context& c){
	cout << endl;
}

WriteVar::WriteVar(char c){
	this->c = c;
}

void WriteVar::interpreta(Context& c){
	cout << c.get(this->c);
}

Read::Read(char c){
	this->c= c;
}

void Read::interpreta(Context& c){
	double tmp;
	cin >> tmp;
	c.inserir(this->c, tmp);
}

Atribuir::Atribuir(char c, Expressao *exp){
	//guarda para futura interpretacao
	this->c = c;
	this->exp=exp;
}

void Atribuir::interpreta(Context &c){	
	c.inserir(this->c,this->exp->avalia(c));
}

For::For(char c, Expressao *exp_ini, int tipo, Expressao *cond, Comandos *cmds){
	this->c = c;
	this->cond=cond;
	this->exp_ini= exp_ini;
	this->tipo = tipo;
	this->cmds= cmds;
}

void For::interpreta(Context &c){
	double temp_inicial = this->exp_ini->avalia(c);
	double temp_cond= this->cond->avalia(c);
	c.inserir(this->c,temp_inicial ); 
	if( this->tipo == 0 ){
		for( int i = temp_inicial; i <= temp_cond; c.inserir(this->c,++i)){
			this->cmds->interpreta(c);
	  }
	}
  else {
		for( int i = temp_inicial; i >= temp_cond; c.inserir(this->c,--i)){
			this->cmds->interpreta(c);
		}
	}
}

While::While(Expressao *cond, Comandos *cmds){
	this->cond = cond;
	this->cmds=cmds;
}

void While::interpreta(Context &c){
	while ( this->cond->avalia(c) ){
		this->cmds->interpreta(c);	
	}
}

If::If(Expressao *cond, Comandos *cmds){
	this->cond = cond;
	this->cmds=cmds;
}

void If::interpreta(Context &c){
	if(this->cond->avalia(c)){
		this->cmds->interpreta(c);
	}
}

IfWithElse::IfWithElse(Expressao *cond, Comandos *cmds_true, Comandos *cmds_false){
	this->cond=cond;
	this->cmds_true=cmds_true;
	this->cmds_false=cmds_false;
}

void IfWithElse::interpreta(Context &c){
	if( this->cond->avalia(c) ){
		this->cmds_true->interpreta(c);
	}
  else{
		this->cmds_false->interpreta(c);
	}	
}
